#lang racket


(require "../list.rkt"
         "../misc.rkt")

(require "domain.rkt"
         "parametric-curve.rkt"
         "parametric-surface.rkt"
         "patch.rkt"
         "segment.rkt")


(provide segmentate-strategy-linear
         segmentate-strategy-integral
         segmentate-curve
         segmentate-surface
         segmentate)


(define (segmentate-strategy-linear)
  (λ (domain segments)
    (let* ((min (domain-min-val domain))
           (max (domain-max-val domain))
           (step (/ (- max min) segments))
           (first-domain (make-domain (domain-min-s domain) min 'closed (+ min step)))
           (last-domain (make-domain 'closed (- max step) (domain-max-s domain) max)))
      (append
       (list first-domain)
       (map 
        (λ (val)
          (make-domain 'closed val 'closed (+ val step)))
        (rest (butlast (range-step min max step))))
       (list last-domain)))))

; edit
(define (segmentate-strategy-integral)
  (error 'segmentate-strategy-integral "Not implemented"))


(define (segmentate-curve parametric n-segments segmentate-strategy)
  (let ((domains (segmentate-strategy (parametric-curve-domain parametric) n-segments)))
    (map (cλ make-segment parametric) domains)))

(define (segmentate-surface parametric u-segments v-segments segmentate-strategy)
  (let ((domains-u (segmentate-strategy (parametric-surface-domain-u parametric) u-segments))
        (domains-v (segmentate-strategy (parametric-surface-domain-v parametric) v-segments)))
    (flatten
     (for/list ((u domains-u))
       (for/list ((v domains-v))
         (make-patch parametric u v))))))

(define (segmentate parametric
                    n-segments
                    (segmentate-strategy (segmentate-strategy-linear)))
  (cond ((parametric-curve? parametric)
         (segmentate-curve parametric n-segments segmentate-strategy))
        ((parametric-surface? parametric)
         (segmentate-surface parametric (first n-segments) (second n-segments) segmentate-strategy))
        (else
         (error 'segmentate "Unhandled parametric object"))))